<?php
import( 'de.ceus-media.framework.krypton.core.Registry' );
import( 'classes.core.Logic' );
import( 'classes.model.User' );
import( 'classes.logic.TemplateUserMailSender' );
import( 'classes.logic.User' );
import( 'de.ceus-media.framework.krypton.exception.Logic' );
/**
 *	Authentication based on User Database Table.
 *	@package		mv2.logic
 *	@extends		Core_Logic
 *	@uses			Model_User
 *	@author			Christian Würker <Christian.Wuerker@CeuS-Media.de>
 *	@since			21.02.2007
 *	@version		0.4
 */
/**
 *	Authentication based on User Database Table.
 *	@package		mv2.logic
 *	@extends		Core_Logic
 *	@uses			Model_User
 *	@author			Christian Würker <Christian.Wuerker@CeuS-Media.de>
 *	@since			21.02.2007
 *	@version		0.4
 */
class Logic_Authentication extends Core_Logic
{
	/**	@var	bool		$companyLeader		Company Leader Indicator */
	protected $companyLeader;
	/**	@var	array		$locationLeads		List of Company IDs */
	protected $locationLeads	= array();
	/**	@var	bool		$trader				Trader Indicator */
	protected $trader;
	/**	@var	bool		$seller				Seller Indicator */
	protected $seller;
	/**	@var	Model_User	$user				Instance of User Model */
	protected $user;
	
	/**
	 *	Constructor.
	 *	@access		public
	 *	@return		void
	 */
	public function __construct()
	{
		parent::__construct();
		$this->user		= new Model_User();
	}
	
	/**
	 *	Tries to authenticate an User.
	 *	@access		protected
	 *	@param		int			$user_id		User ID
	 *	@param		string		$password		User Password
	 *	@return		bool
	 */
	protected function authenticate( $user_id, $password )
	{
		$session	= Framework_Krypton_Core_Registry::getStatic( 'session' );
		if( $this->validatePassword( $user_id, $password ) )
		{
			$session->set( "authenticated", TRUE );
			$session->set( "uid", $user_id );
			return TRUE;
		}
		return false;
	}
	
	/**
	 *	Returns ID of currently authenticated User.
	 *	@access		public
	 *	@return		int
	 */
	static public function getCurrentUser()
	{
		$session	= Framework_Krypton_Core_Registry::getStatic( 'session' );
		return (int)$session->get( "uid" );
	}

	/**
	 *	Returns all Location IDs where an User is Leader of.
	 *	@access		public
	 *	@return		bool
	 */
	public function getLeadLocations( $user_id )
	{
		return $this->locationLeads;
	}

	/**
	 *	Returns User ID by its Username.
	 *	@access		public
	 *	@param		string		$username	User Name (must be unique)
	 *	@return		int
	 */
	public function getUidFromUsername( $username )
	{
		return $this->user->getUidFromUsername( $username );
	}
	
	/**
	 *	Returns Username by its User ID.
	 *	@access		public
	 *	@param		int			user_id		User ID
	 *	@return		string
	 */
	public function getUsernameFromUid( $user_id )
	{
		$model	= new Model_User( $user_id );
		return $model->getUsernameFromUid( $user_id );
	}
	
	/**
	 *	Increases Page Count of User if is authenticated.
	 *	@access		public
	 *	@return		void
	 */
	public function increasePageCount()
	{
		if( $this->isAuthenticated() )
		{
			$user	= new Model_User( $this->getCurrentUser() );
			$data	= $user->get();
			$count	= $data['count_pages'] + 1;
			$user->update( array( 'count_pages' => $count ) );
		}
	}

	/**
	 *	Increases Page Count of User if is authenticated.
	 *	@access		public
	 *	@return		void
	 */
	public function increaseLoginCount()
	{
		if( $this->isAuthenticated() )
		{
			$user	= new Model_User( $this->getCurrentUser() );
			$data	= $user->get();
			$count	= $data['count_logins'] + 1;
			$user->update( array( 'count_logins' => $count ) );
		}
	}

	/**
	 *	Indicates whether an User is already authenticated.
	 *	@access		public
	 *	@return		bool
	 */
	public function isAuthenticated()
	{
		$session	= Framework_Krypton_Core_Registry::getStatic( 'session' );
		if( $session->get( "authenticated" ) )
			return TRUE;
		return false;
	}

	/**
	 *	Indicates whether an User is a Company Leader.
	 *	@access		public
	 *	@return		bool
	 */
	public function isCompanyLeader()
	{
		return $this->companyLeader;
	}

	/**
	 *	Indicates whether an User is a Location Leader.
	 *	@access		public
	 *	@return		bool
	 */
	public function isLocationLeader()
	{
		return (bool)count( $this->locationLeads );
	}

	/**
	 *	Indicates whether an User is a Trader.
	 *	@access		public
	 *	@return		bool
	 */
	public function isTrader()
	{
		return $this->trader;
	}

	/**
	 *	Indicates whether an User is a Seller on the curren Platform.
	 *	@access		public
	 *	@return		bool
	 */
	public function isSeller()
	{
		return $this->seller;
	}

	/**
	 *	@todo		Code Documentation
	 */
	public function login( $data, $prefix = "" )
	{
		$data	= $this->removePrefixFromFields( $data, $prefix );
		if( $this->validateForm( 'auth', 'loginUserControl', $data ) )
		{
			if( $user_id = $this->user->getUidFromUsername( $data['username'] ) )
			{
				$user_logic = new Logic_User();
				if( $this->authenticate( $user_id, $data['password'] ) )
				{
					$this->user->focusPrimary( $user_id );
					$user	= $this->user->get();
					$count	= $user['count_logins'] + 1;
					$data	= array(
						'logged'			=> time(),
						'count_logins'		=> $count,
						'count_attempts'	=> 0,
						);
					$this->user->update( $data );
					return TRUE;
				}
				else
				{
					$this->user->focusPrimary( $user_id );
					$user	= $this->user->get();
					$count	= $user['count_attempts'] + 1;
					$this->user->update( array( 'count_attempts' => $count ) );
					throw new Framework_Krypton_Exception_Logic( 'error_password_invalid' );
				}
			}
			else
				throw new Framework_Krypton_Exception_Logic( 'error_user_invalid' );
		}
	}
	
	/**
	 *	Logs out the current User.
	 *	@access			public
	 *	@return			bool
	 */
	public function logout()
	{
		$session	= Framework_Krypton_Core_Registry::getStatic( 'session' );
		$session->set( "authenticated", false );
		$session->set( "uid", false );
		$this->roles	= array();
		return TRUE;
	}

	/**
	 *	Validates a Password for a given User ID.
	 *	@access		public
	 *	@param		int			$user_id
	 *	@param		string		$password
	 *	@return		bool
	 */
	public function validatePassword( $user_id, $password )
	{
		$this->user->focusPrimary( $user_id );
		$data = $this->user->get( TRUE );
		if( !$this->user->exists() )
			throw new Framework_Krypton_Exception_Logic( 'user_no_existing' );
		$this->user->defocus();
		return $data['password'] == md5( $password );
	}
	
	/**
	 *	Indicated whether current User has Right to Object and Action.
	 *	@access		public
	 *	@param		string		object		Object Name
	 *	@param		string		action		Action Name
	 *	@return		int
	 *	@deprecated	not used anymore
	 */
	public function hasAccessToPage( $page_id )
	{
		$controller	= Framework_Krypton_Core_Registry::getStatic( 'controller' );
		$doc	= $controller->getDocument();
		$list	= array();		
		$link 	= $doc->getElementById( $page_id );
		if( $link )
		{
			$roles	= $link->getElementsByTagName( 'roles' )->item( 0 );
			foreach( $roles->childNodes as $role )
				$list[]	= $role->nodeName;

			if( in_array( "public", $list ) )
				return TRUE;
			if( $this->isAuthenticated() )
			{
				if( in_array( "inside", $list ) )
					return TRUE;

				//  --  TRADER  --  //			
				if( $this->isTrader() && in_array( "trader", $list ) )
					return TRUE;

				//  --  SELLER  --  //			
				if( $this->isSeller() && in_array( "seller", $list ) )
					return TRUE;

				//  --  LOCATION LEADER  --  //			
				if( $this->isLocationLeader() && in_array( "location_leader", $list ) )
					return TRUE;

				//  --  COMPANY LEADER  --  //			
				if( $this->isCompanyLeader() && in_array( "company_leader", $list ) )
					return TRUE;

			}
			else if( in_array( 'outside', $list ) )
				return TRUE;
		}
		return FALSE;
	}
	
	/**
	 *	Finds first accessible Page depending on Authentication Status.
	 *	@access		public
	 *	@return		string
	 */
	public function getFirstAccessiblePage()
	{
		$controller	= Framework_Krypton_Core_Registry::getStatic( 'controller' );
		$defaults	= $controller->getDefaultPages();
		$doc		= $controller->getDocument();

		foreach( $defaults as $page_id )
		{
			$list	= array();
			$link	= $doc->getElementById( $page_id );
			if( $link )
			{
				$roles	= $link->parentNode->getElementsByTagName( 'roles' )->item( 0 );
				foreach( $roles->childNodes as $role )
					$list[]	= $role->nodeName;

				if( in_array( "public", $list ) )
					return $page_id;
				if( $this->isAuthenticated() )
				{
					if( in_array( "inside", $list ) )
						return $page_id;
				}
				else
				{
					if( in_array( "outside", $list ) )
						return $page_id;
				}
			}
		}
		return NULL;
	}
}
?>
